package com.ff.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.ServiceException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.PolicyConditions;
import com.ff.dao.OssDao;

import net.sf.json.JSONObject;

@Service
public class OssServiceImpl implements OssService {

	@Value("${oss.host}")
	private String host; // oss-cn-beijing.aliyuncs.com

	@Value("${oss.accessid}")
	private String accessid; // Tk9bWYtSlxy3QFbJ

	@Value("${oss.accesskey}")
	private String accesskey; // esTS8FVcwgWamJ7BctT2ZThZOPi4Rv

	@Value("${oss.bucket}")
	private String bucket; // studyjava;
	
	@Value("${oss.expiration}")
	private Integer expiration; // 2000;
	
	@Value("${oss.tempdir}")
	private String tempdir; // tempdir
	
	@Value("${oss.callbackurl}")
	private String callbackurl; //回调接口路径

	@Autowired
	private OssDao ossDao;

	@Override
	public boolean createFolder(String folderName) {
		boolean created = false;
		OSSClient client = new OSSClient(host, accessid, accesskey);
		try {
			// ossDao.ensureBucket(client, bucket); // 没必要经常性地确认bucket存在
			if (ossDao.findObject(client, bucket, folderName) == null) {
				ossDao.createFolder(client, bucket, folderName);
			}
			created = true;
		} catch (ServiceException e) {
			System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
			e.printStackTrace();
		} catch (ClientException e) {
			System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return created;
	}

	@Override
	public String uploadFile(String key, String contentType, byte[] bytes) {
		String uri = null;
		OSSClient client = new OSSClient(host, accessid, accesskey);
		try {
			// ossDao.ensureBucket(client, bucket); // 没必要经常性地确认bucket存在
			// if (ossDao.findObject(client, bucket, folderName + "/") == null)
			// {
			// ossDao.createFolder(client, bucket, folderName + "/");
			// } // 没必要确认folder的存在
			InputStream input = new ByteArrayInputStream(bytes);
			// String key = ((folderName != null) ? folderName + "/" : "") +
			// fileName;
			ossDao.uploadFile(client, bucket, key, contentType, bytes.length, input);
			uri = ossDao.getObjectUri(client, bucket, key);
			input = null;
		} catch (ServiceException e) {
			e.printStackTrace();
		} catch (ClientException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return uri;
	}

	@Override
	public String getPictureUri(String key) {
		String uri = null;
		OSSClient client = new OSSClient(host, accessid, accesskey);
		try {
			uri = ossDao.getObjectUri(client, bucket, key);
		} catch (ServiceException e) {
			System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
			e.printStackTrace();
		} catch (ClientException e) {
			System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return uri;
	}

	@Override
	public boolean deleteFile(String key) {
		OSSClient client = new OSSClient(host, accessid, accesskey);
		boolean deleted = false;
		try {
			// String key = ((folderName != null) ? folderName + "/" : "") +
			// fileName;
			deleted = ossDao.deleteObject(client, bucket, key);
		} catch (ServiceException e) {
			System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
			e.printStackTrace();
		} catch (ClientException e) {
			System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return deleted;
	}

	@Override
	public void clearBucket() {
		ObjectListing listObject = null;
		boolean haveObject = false;
		boolean havePrefix = false;
		do {
			OSSClient client = new OSSClient(host, accessid, accesskey);
			try {
				listObject = ossDao.listObject(client, bucket, "1");
				// 遍历所有Object
				System.out.println("Objects:");
				List<OSSObjectSummary> listObjectSumary = listObject.getObjectSummaries();
				if ((listObjectSumary != null) && (listObjectSumary.size() > 0)) {
					haveObject = true;
					for (OSSObjectSummary objectSummary : listObjectSumary) {
						String key = objectSummary.getKey();
						System.out.println(key);
						client.deleteObject(bucket, key);
					}
				} else {
					haveObject = false;
				}
				// 遍历所有CommonPrefix
				System.out.println("\nCommonPrefixs:");
				List<String> listCommonPrefix = listObject.getCommonPrefixes();
				if ((listCommonPrefix != null) && (listCommonPrefix.size() > 0)) {
					havePrefix = true;
					for (String commonPrefix : listCommonPrefix) {
						System.out.println(commonPrefix);
					}
				} else {
					havePrefix = false;
				}
			} catch (ServiceException e) {
				System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
				e.printStackTrace();
			} catch (ClientException e) {
				System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
			client = null;
		} while (haveObject || havePrefix);
	}

	@Override
	public String[] uploadFiles(String folderName, Map<String, MultipartFile> mapfiles) {
		// 调用OSS的DAO接口获取存储路径
		if (mapfiles == null) {
			return new String[0];
		}
		String[] picpaths = new String[mapfiles.size()];
		String filePrefix = DateTime.now().toString("yyyyMMddHHmmss") + "-";
		int i = 0;
		for (Map.Entry<String, MultipartFile> entry : mapfiles.entrySet()) {
			MultipartFile file = entry.getValue();
			if (!file.isEmpty()) {
				// 保存pics数据并获取链接
				String dataName = entry.getKey();
				String key = StringUtils.isEmpty(folderName) ? (filePrefix + dataName)
						: (folderName + "/" + filePrefix + dataName);
				try {
					byte[] bytes = file.getBytes();
					picpaths[i++] = uploadFile(key, file.getContentType(), bytes);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return picpaths;
	}

	@Override
	public String uploadFile(String folderName, String fileName, File file) {
		// 调用OSS的DAO接口获取存储路径
		String filePrefix = DateTime.now().toString("yyyyMMddHHmmss") + "-";
		String key = StringUtils.isEmpty(folderName) ? (filePrefix + fileName)
				: (folderName + "/" + filePrefix + fileName);
		try {
			byte[] buffer = null;
			FileInputStream fis = new FileInputStream(file);
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			byte[] b = new byte[1024];
			int n;
			while ((n = fis.read(b)) != -1) {
				bos.write(b, 0, n);
			}
			fis.close();
			bos.close();
			buffer = bos.toByteArray();
			return uploadFile(key, "", buffer);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public String uploadFile(String folderName, File file) {
		return uploadFile(folderName, file.getName(), file);
	}

	@Override
	public String uploadFile(File file) {
		return uploadFile(null, file.getName(), file);

	}

	/**
	 * @Title: uploadFiles
	 * @Description: TODO
	 * @param mapfiles
	 * @return
	 * @see com.ff.service.OssService#uploadFiles(java.util.Map)
	 */
	@Override
	public String[] uploadFiles(Map<String, MultipartFile> mapfiles) {
		return uploadFiles(null, mapfiles);
	}

	/**
	 * @Title: uploadFiles
	 * @Description: TODO
	 * @param multipartFile
	 * @return
	 * @see com.ff.service.OssService#uploadFiles(org.springframework.web.multipart.MultipartFile)
	 */
	@Override
	public String[] uploadFiles(MultipartFile multipartFile) {
		// 调用OSS的DAO接口获取存储路径
		if (multipartFile == null) {
			return new String[0];
		}
		String[] picpaths = new String[1];
		String filePrefix = DateTime.now().toString("yyyyMMddHHmmss") + "-";
		int i = 0;
		MultipartFile file = multipartFile;
		if (!file.isEmpty()) {
			String dataName = file.getOriginalFilename();
			String key = filePrefix + dataName;
			try {
				byte[] bytes = file.getBytes();
				picpaths[i++] = uploadFile(key, file.getContentType(), bytes);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return picpaths;
	}

	/**
	 * @Title: getPrivatePicUri
	 * @Description: TODO
	 * @param key
	 * @return
	 * @see com.ff.service.OssService#getPrivatePicUri(java.lang.String)
	 */
	@Override
	public String getPrivatePicUri(String key) {
		String uri = null;
		OSSClient client = new OSSClient(host, accessid, accesskey);
		try {
			uri = ossDao.getPrivatePicUri(client, bucket, key, expiration);
		} catch (ServiceException e) {
			System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
			e.printStackTrace();
		} catch (ClientException e) {
			System.err.println(e.getErrorCode() + ":" + e.getErrorMessage());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return uri;
	}

	/**
	 * @Title: createPolicy
	 * @Description: TODO
	 * @return
	 * @throws UnsupportedEncodingException 
	 * @see com.ff.service.OssService#createPolicy()
	 */
	@Override
	public String createPolicy() throws UnsupportedEncodingException {
		long expireTime = 30;
    	long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
        Date expiration = new Date(expireEndTime);
        PolicyConditions policyConds = new PolicyConditions();
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
        policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, tempdir);
        OSSClient client = new OSSClient(host, accessid, accesskey);
        String postPolicy = client.generatePostPolicy(expiration, policyConds);
        byte[] binaryData = postPolicy.getBytes("utf-8");
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = client.calculatePostSignature(postPolicy);
        
        JSONObject js = new JSONObject();
        js.put("callbackUrl", callbackurl);
        String fileName = UUID.randomUUID().toString().replaceAll("-", "").concat(".jpg");
		js.put("callbackBody", "filename="+fileName);
        js.put("callbackBodyType", "application/x-www-form-urlencoded");
        		
        Map<String, Object> respMap = new LinkedHashMap<>();
        respMap.put("accessid", accessid);
        respMap.put("policy", encodedPolicy);
        respMap.put("signature", postSignature);
        //respMap.put("expire", formatISO8601Date(expiration));
        respMap.put("dir", tempdir);
        respMap.put("host", "http://".concat(bucket.concat(".").concat(host)));
        respMap.put("expire", String.valueOf(expireEndTime / 1000));
        respMap.put("callback", BinaryUtil.toBase64String(js.toString().getBytes()));
        respMap.put("filename", fileName);
        JSONObject ja1 = JSONObject.fromObject(respMap);
		return ja1.toString();
	}
}
